namespace DukeyTbker.API
{
    using System;
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Net;
    using System.Reflection;
    using System.Security.Cryptography;
    using System.Text;
    using System.Web.Services;
    using System.Web.Services.Description;
    using System.Web.Services.Discovery;
    using System.Web.Services.Protocols;
    using System.Xml.Schema;
    using System.Xml.Serialization;

    [WebService(Namespace="http://tempuri.org/"), ToolboxItem(false), WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)]
    public class WebServiceProxy : WebService
    {
        private string _assName;
        private string _assPath;
        private object _instance;
        private Type _typeName;
        private string _wsdlName;
        private string _wsdlNamespace;
        private string _wsdlUrl;

        public WebServiceProxy(string wsdlUrl)
        {
            this._wsdlUrl = string.Empty;
            this._wsdlName = string.Empty;
            this._wsdlNamespace = "DukeyTbker.API";
            this._assName = string.Empty;
            this._assPath = string.Empty;
            this._wsdlUrl = wsdlUrl;
            string str = getWsclassName(wsdlUrl);
            this._wsdlName = str;
            this._assName = string.Format(this._wsdlNamespace, str);
            this._assPath = Path.GetTempPath() + this._assName + this.getMd5Sum(this._wsdlUrl) + ".dll";
            this.CreateServiceAssembly();
        }

        public WebServiceProxy(string wsdlUrl, string wsdlName)
        {
            this._wsdlUrl = string.Empty;
            this._wsdlName = string.Empty;
            this._wsdlNamespace = "DukeyTbker.API";
            this._assName = string.Empty;
            this._assPath = string.Empty;
            this._wsdlUrl = wsdlUrl;
            this._wsdlName = wsdlName;
            this._assName = this._wsdlNamespace;
            this._assPath = Path.GetTempPath() + this._assName + this.getMd5Sum(this._wsdlUrl) + ".dll";
            this.CreateServiceAssembly();
        }

        private bool checkCache()
        {
            return System.IO.File.Exists(this._assPath);
        }

        private void checkForImports(string baseWsdlUrl, ServiceDescriptionImporter importer)
        {
            DiscoveryClientProtocol protocol = new DiscoveryClientProtocol();
            protocol.DiscoverAny(baseWsdlUrl);
            protocol.ResolveAll();
            foreach (object obj2 in protocol.Documents.Values)
            {
                if (obj2 is ServiceDescription)
                {
                    importer.AddServiceDescription((ServiceDescription) obj2, null, null);
                }
                if (obj2 is XmlSchema)
                {
                    importer.Schemas.Add((XmlSchema) obj2);
                }
            }
        }

        private void copyTempAssembly(string pathToAssembly)
        {
            System.IO.File.Copy(pathToAssembly, this._assPath);
        }

        private void CreateServiceAssembly()
        {
            if (this.checkCache())
            {
                this.initTypeName();
            }
            else if (!string.IsNullOrEmpty(this._wsdlUrl))
            {
                try
                {
                    WebClient client = new WebClient();
                    ServiceDescription serviceDescription = ServiceDescription.Read(client.OpenRead(this._wsdlUrl));
                    ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
                    importer.ProtocolName = "Soap";
                    importer.Style = ServiceDescriptionImportStyle.Client;
                    importer.CodeGenerationOptions = CodeGenerationOptions.GenerateNewAsync | CodeGenerationOptions.GenerateProperties;
                    importer.AddServiceDescription(serviceDescription, null, null);
                    CodeNamespace namespace2 = new CodeNamespace(this._assName);
                    CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
                    codeCompileUnit.Namespaces.Add(namespace2);
                    this.checkForImports(this._wsdlUrl, importer);
                    importer.Import(namespace2, codeCompileUnit);
                    CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
                    CompilerParameters options = new CompilerParameters();
                    options.ReferencedAssemblies.Add("System.dll");
                    options.ReferencedAssemblies.Add("System.XML.dll");
                    options.ReferencedAssemblies.Add("System.Web.Services.dll");
                    options.ReferencedAssemblies.Add("System.Data.dll");
                    options.GenerateExecutable = false;
                    options.GenerateInMemory = false;
                    options.IncludeDebugInformation = false;
                    CompilerResults results = provider.CompileAssemblyFromDom(options, new CodeCompileUnit[] { codeCompileUnit });
                    provider.Dispose();
                    if (results.Errors.HasErrors)
                    {
                        string message = string.Format("编译错误:{0}错误！", results.Errors.Count);
                        foreach (CompilerError error in results.Errors)
                        {
                            message = message + error.ErrorText;
                        }
                        throw new Exception(message);
                    }
                    this.copyTempAssembly(results.PathToAssembly);
                    this.initTypeName();
                }
                catch (Exception exception)
                {
                    throw new Exception(exception.Message);
                }
            }
        }

        public void ExecuteNoQuery(string methodName, object[] param)
        {
            try
            {
                if (this._typeName == null)
                {
                    throw new TypeLoadException("Web服务访问类名【" + this._wsdlName + "】不正确，请检查！");
                }
                MethodInfo method = this._typeName.GetMethod(methodName);
                if (method == null)
                {
                    throw new TypeLoadException("Web服务访问方法名【" + methodName + "】不正确，请检查！");
                }
                try
                {
                    if (param == null)
                    {
                        method.Invoke(this.Instance, null);
                    }
                    else
                    {
                        method.Invoke(this.Instance, param);
                    }
                }
                catch (TypeLoadException exception)
                {
                    throw new TypeLoadException("Web服务访问方法【" + methodName + "】参数个数不正确，请检查！", new TypeLoadException(exception.StackTrace));
                }
            }
            catch (Exception exception2)
            {
                throw new Exception(exception2.Message, new Exception(exception2.StackTrace));
            }
        }

        public object ExecuteQuery(string methodName, object[] param)
        {
            List<string> list = new List<string>();
            List<string> list2 = new List<string>();
            List<string> list3 = new List<string>();
            object[] objArray = new object[3];
            try
            {
                if (this._typeName == null)
                {
                    throw new TypeLoadException("Web服务访问类名【" + this._wsdlName + "】不正确，请检查！");
                }
                MethodInfo method = this._typeName.GetMethod(methodName);
                if (method == null)
                {
                    throw new TypeLoadException("Web服务访问方法名【" + methodName + "】不正确，请检查！");
                }
                try
                {
                    if (param == null)
                    {
                        return method.Invoke(this.Instance, null);
                    }
                    list.Add("Hello ");
                    list.Add("WebService ");
                    list.Add(" ! ");
                    list2.Add("I ");
                    list2.Add("am ");
                    list2.Add("test ");
                    list3.Add("do ");
                    list3.Add("it ");
                    list3.Add("now ");
                    objArray[0] = list;
                    objArray[1] = list2;
                    objArray[2] = list3;
                    return method.Invoke(this.Instance, new object[] { objArray });
                }
                catch (TypeLoadException exception)
                {
                    throw new TypeLoadException("Web服务访问方法【" + methodName + "】参数个数不正确，请检查！", new TypeLoadException(exception.StackTrace));
                }
            }
            catch (Exception exception2)
            {
                throw new Exception(exception2.Message, new Exception(exception2.StackTrace));
            }
            return null;
        }

        private string getMd5Sum(string string_0)
        {
            System.Text.Encoder encoder = Encoding.Unicode.GetEncoder();
            byte[] bytes = new byte[string_0.Length * 2];
            encoder.GetBytes(string_0.ToCharArray(), 0, string_0.Length, bytes, 0, true);
            byte[] buffer2 = new MD5CryptoServiceProvider().ComputeHash(bytes);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < buffer2.Length; i++)
            {
                builder.Append(buffer2[i].ToString("X2"));
            }
            return builder.ToString();
        }

        private static string getWsclassName(string wsdlUrl)
        {
            string[] strArray = wsdlUrl.Split(new char[] { '/' });
            return strArray[strArray.Length - 1].Split(new char[] { '.' })[0];
        }

        private void initTypeName()
        {
            Assembly assembly = Assembly.LoadFrom(this._assPath);
            Type[] types = assembly.GetTypes();
            string name = "";
            foreach (Type type in types)
            {
                if (type.BaseType == typeof(SoapHttpClientProtocol))
                {
                    name = type.Name;
                    break;
                }
            }
            this._typeName = assembly.GetType(this._assName + "." + name);
        }

        private object Instance
        {
            get
            {
                if (this._instance == null)
                {
                    this._instance = Activator.CreateInstance(this._typeName);
                    return this._instance;
                }
                return this._instance;
            }
        }
    }
}

